from django.shortcuts import render
from django import http
from django.views import View
import json
from django_redis import get_redis_connection
from utility.views import LoginRequiredJsonMixin
from apps.goods.models import SKU
import pickle, base64


# Create your views here.

# 显示我的购物车
class MyCartsView(View):

    def get(self, request):

        if request.user.is_authenticated:
            # 已登录用户
            user_id = request.user.id
            redis_conn = get_redis_connection('carts_code')
            redis_dict = redis_conn.hgetall('carts_%s' % user_id)
            cart_skus = []
            for sku_id in redis_dict.keys():
                sku_conn = SKU.objects.get(id=int(sku_id))
                cart_skus.append({
                    'id': int(sku_id),
                    'name': sku_conn.name,
                    'count': int(redis_dict[sku_id]),
                    'url': sku_conn.default_image.url

                })
            return http.JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_skus': cart_skus})

        # else:
        #     pass


# 购物车的全选和反全选
class SeletedView(View):

    def put(self, request):

        # 1	前端根据用户的交互情况==>将是否全选==>传到后端
        # 2	后端接收参数==>判断参数有效性==>判断用户的登陆状态
        json_dict = json.loads(request.body.decode())
        selected = json_dict.get('selected')
        if selected == None:
            return http.JsonResponse({'code': 400, 'errmsg': '参数错误'})

        if not isinstance(selected, bool):
            return http.JsonResponse({'code': 400, 'errmsg': '参数错误'})

        if request.user.is_authenticated:
            # 3	已登录状态==>根据用户ID==>查询数据库==>修改redis数据==>返回响应
            user_id = request.user.id
            redis_conn = get_redis_connection('carts_code')
            pl = redis_conn.pipeline()
            skus_dict = pl.hgetall('carts_%s' % user_id)
            if selected:
                # HGETALL key
                # 返回哈希表 key 中，所有的域和值。
                pl.sadd('selected_%s' % user_id, *skus_dict.keys())

            else:
                pl.srem('selected_%s' % user_id, *skus_dict.keys())
            pl.execute()
            return http.JsonResponse({'code': 0, 'errmsg': 'ok'})

        else:
            # 4未登录状态==>根据获取cookie数据信息==>修改cookie数据==>返回响应
            cookie_str = request.COOKIES.get('carts')
            if cookie_str:
                cookie_dict = pickle.loads(base64.b64decode(cookie_str.encode()))
            else:
                cookie_dict = {}

            sku_ids_list = cookie_dict.keys()

            for sku_id in sku_ids_list:
                if selected:
                    cookie_dict[sku_id]['selected'] = selected
                else:
                    cookie_dict[sku_id]['selected'] = selected

            cookie_new_str = base64.b64encode(pickle.dumps(cookie_dict)).decode()

            response = http.JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('carts', cookie_new_str)
            return response


# 购物车的增删改查
class CartsView(View):
    # POST 加入购物车
    # GET 展示购物车
    # PUT 修改购物车数据
    # DELETE 删除购物车数据

    def delete(self, request):

        # 效果:把商品从购物车移除
        # 1	前端根据用户的交互情况==>将商品需要删除的ID==>传到后端
        # 2	后端接收参数==>判断参数有效性==>判断用户的登陆状态
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        if not all([sku_id]):
            return http.JsonResponse({'code': 400, 'errmsg': '缺少必须参数'})
        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.JsonResponse({'code': 400, 'errmsg': 'sku_id参数错误'})

        if request.user.is_authenticated:
            # 3	已登录状态==>根据用户ID==>查询数据库==>删除redis数据库对应商品ID的数据==>返回响应
            user_id = request.user.id
            redis_conn = get_redis_connection('carts_code')
            pl = redis_conn.pipeline()
            # HDEL key field [field ...]
            # 删除哈希表 key 中的一个或多个指定域，不存在的域将被忽略。
            pl.hdel('carts_%s' % user_id, sku_id)
            pl.srem('selected_%s' % user_id, sku_id)
            pl.execute()

            return http.JsonResponse({'code': 0, 'errmsg': 'ok'})

        else:

            # 4	未登录状态==>根据获取cookie数据信息==>删除对应的数据信息==>返回响应
            cookie_str = request.COOKIES.get('carts')
            if cookie_str:
                cookie_dict = pickle.loads(base64.b64decode(cookie_str.encode()))
            else:
                cookie_dict = {}
            if sku_id in cookie_dict.keys():
                del cookie_dict[sku_id]

            cookie_new_str = base64.b64encode(pickle.dumps(cookie_dict)).decode()
            response = http.JsonResponse({'code': 0, 'errmsg': 'ok'})
            response.set_cookie('carts', cookie_new_str)
            return response

    def put(self, request):
        # 1	前端根据用户的交互情况==>将商品修改后数量/商品ID/勾选状况==>传到后端
        # 2	后端接收参数==>判断参数有效性==>判断用户的登陆状态
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        count = json_dict.get('count')
        selected = json_dict.get('selected')
        if not all([sku_id, count, sku_id]):
            return http.JsonResponse({'code': 400, 'errmsg': '缺少必须参数'})

        try:
            SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.JsonResponse({'code': 400, 'errmsg': 'sku_id参数错误'})
        try:
            count = int(count)
        except Exception:
            return http.JsonResponse({'code': 400, 'errmsg': 'count参数错误'})
        if not isinstance(selected, bool):
            return http.JsonResponse({'code': 400, 'errmsg': 'selected参数错误'})

        if request.user.is_authenticated:
            # 3	已登录状态==>获取当前用户ID==>根据ID查询redis数据库获取到对应数据==>对数据重新修改==>返回给前端,实现局部刷新
            user_id = request.user.id
            redis_conn = get_redis_connection('carts_code')
            # HSET key field value
            # 将哈希表 key 中的域 field 的值设为 value 。
            # 如果 key 不存在，一个新的哈希表被创建并进行 HSET 操作。
            # 如果域 field 已经存在于哈希表中，旧值将被覆盖。
            redis_conn.hset('carts_%s' % user_id, sku_id, count)
            pl = redis_conn.pipeline()
            if selected:
                # SADD key member [member ...]
                # 将一个或多个 member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略。
                pl.sadd('selected_%s' % user_id, sku_id)
            # SREM key member [member ...]
            # 移除集合 key 中的一个或多个 member 元素，不存在的 member 元素会被忽略。
            # 当 key 不是集合类型，返回一个错误。
            else:
                pl.srem('selected_%s' % user_id, sku_id)
            pl.execute()
            cart_sku = {
                'sku_id': sku_id,
                'count': count,
                'selected': selected
            }
            return http.JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_sku': cart_sku})


        else:
            # 4	未登录状态==>获取当前cookie中的数据==>对保存的商品信息重新赋值==>返回给前端,实现局部刷新==>加密重新保存
            cookie_str = request.COOKIES.get('carts')
            if cookie_str:
                cookie_dict = pickle.loads(base64.b64decode(cookie_str.encode()))
                if sku_id not in cookie_dict.keys():
                    return http.JsonResponse({'code': 400, 'errmsg': 'sku_id参数错误'})
            else:
                cookie_dict = {}
            cookie_dict[sku_id] = {
                'count': count,
                'selected': selected
            }
            cookie_new_str = base64.b64encode(pickle.dumps(cookie_dict)).decode()
            cart_sku = {
                'count': count,
                'selected': selected
            }

            response = http.JsonResponse({'code': 400, 'errmsg': 'ok', 'cart_sku': cart_sku})
            response.set_cookie('carts', cookie_new_str)
            return response

    def get(self, request):
        if request.user.is_authenticated:
            # 登录用户
            user_id = request.user.id
            redis_conn = get_redis_connection('carts_code')
            # HGETALL key 返回哈希表 key 中，所有的域和值
            good_infos = redis_conn.hgetall('carts_%s' % user_id)
            good_infos_selected = redis_conn.smembers('selected_%s' % user_id)
            cookie_dict = {}

            for sku_id, count in good_infos.items():
                # print(type(sku_id))
                # print(type(count))
                cookie_dict[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in good_infos_selected
                }

        else:
            # 未登录用户
            # 解析cooki信息获取对于数据,获取得到是byte字节数据
            cookie_str = request.COOKIES.get('carts')

            if cookie_str:
                cookie_str_byte = cookie_str.encode()
                # 解密
                cookie_dict = pickle.loads(base64.b64decode(cookie_str_byte))
                # cookie_dict = pickle.loads(base64.b64decode(cookie_str))
            else:
                cookie_dict = {}

            # 取出字典中所有的key 既得到所有商品的ID
        sku_ids = cookie_dict.keys()

        cart_skus = []
        # sku_id_list = SKU.objects.filter(id__in=sku_ids)
        # 便利得到每个商品的ID
        for sku_id in sku_ids:
            sku_conn = SKU.objects.get(id=sku_id)
            print(type(sku_conn))
            cart_skus.append({
                'id': sku_conn.id,
                'name': sku_conn.name,
                'default_image_url': sku_conn.default_image.url,
                'price': sku_conn.price,
                'count': cookie_dict[sku_conn.id]['count'],
                'selected': cookie_dict[sku_conn.id]['selected'],
                'amount': sku_conn.price * cookie_dict[sku_conn.id]['count']
            })
        return http.JsonResponse({'code': 0, 'errmsg': 'ok', 'cart_skus': cart_skus})

    def post(self, request):
        '''实现加入购物车'''
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        count = json_dict.get('count')
        selected = json_dict.get('selected', True)

        if not all([sku_id, count]):
            return http.JsonResponse({'code': 400, 'errmsg': '缺少必须参数'})

        if request.user.is_authenticated:
            # 登录用户
            redis_conn = get_redis_connection('carts_code')
            ple = redis_conn.pipeline()
            user_id = request.user.id
            selected_id = 'selected_%s' % user_id
            #	HINCRBY KEY_NAME FIELD_NAME INCR_BY_NUMBER
            # redis_conn.hmset('carts_%s' % request.user.id,
            #                  sku_id,
            #                  count)
            ple.hincrby('carts_%s' % user_id,
                        sku_id,
                        int(count))
            ple.sadd(selected_id,
                     sku_id)
            ple.execute()
            return http.JsonResponse({'code': 0, 'errmsg': '加入购物车成功'})
        else:
            # 取出cookie密文字符串
            cookie_str = request.COOKIES.get('carts')
            # print(type(cookie_str))
            # 判断字符串是否为空
            if cookie_str:
                cookie_str_byte = cookie_str.encode()
                cookie_dict = pickle.loads(base64.b64decode(cookie_str_byte))
            else:
                cookie_dict = {}
            # 判断要添加是否已经存在
            if sku_id in cookie_dict.keys():
                old_count = cookie_dict[sku_id]['count']
                count += old_count

            # 如果是新添加==>新增加数据
            # 如果是已经存在的==>更改了数据
            cookie_dict[sku_id] = {
                'count': count,
                'selected': selected
            }

            # 再对cookie_dict加密保存
            cookie_new_str_byte = base64.b64encode(pickle.dumps(cookie_dict))
            cookie_new_str = cookie_new_str_byte.decode()

            response = http.JsonResponse({'code': 0, 'errmsg': '加入购物车成功'})
            response.set_cookie('carts', cookie_new_str)
            return response
